/*   Shotscreens
 *   Copyright (C) 2010, Vadim Zakondyrin (http://crystalnix.com)
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "qgraphicspainter.h"
#include <QGraphicsScene>
#include <QGraphicsLineItem>
#include <QMouseEvent>
#include "qgraphicsarrowitem.h"
#include "qgraphicsbrushitem.h"
#include "qgraphicstextrectitem.h"
#include "QInputDialog"
#include "QMessageBox"
#include "texttodraw.h"
#include <QDesktopWidget>
#include <QCloseEvent>
QGraphicsPainter::QGraphicsPainter(QWidget *parent) : QGraphicsView(parent)
{

    initializationPainter();
}

QGraphicsPainter::QGraphicsPainter(QGraphicsScene *scene, QWidget *parent) : QGraphicsView(scene, parent)
{

    initializationPainter();
}

QGraphicsPainter::~QGraphicsPainter()
{
    delete selectedItem;
}

void QGraphicsPainter::initializationPainter()
{
    setRenderHint(QPainter::Antialiasing);
    paintproperties.setModal(true);
    holdLeftButton = false;

    selectedItem = new QGraphicsBound;
    undo_item_index=-1;
}
void QGraphicsPainter::closeEvent(QCloseEvent *event)
{
      undo_item_index=-1;

      for(int i=0;i<graphicsItems.count();i++)
      {
            QGraphicsItem *CurrentItem=graphicsItems.at(i);
            scene()->removeItem(CurrentItem);
            scene()->update();
            delete CurrentItem;
      }
      graphicsItems.clear();
      close();
      deleteLater();
      event->accept();

}

void QGraphicsPainter::Redo()
{
    if(redo_enabled)
    {
        QGraphicsItem *redo_item=/*graphicsItems.at(undo_item_index)*/removedItems.takeLast();
        redo_item->setPos(undo_item_pos.takeLast());
        graphicsItems.append(redo_item);
        scene()->update();

        undo_item_index=-1;
    }

    if(removedItems.isEmpty()) redo_enabled=false;
    emit undoEnabled(true);
}

bool QGraphicsPainter::IsSceneEmpty()
{
    int enabled_elements=0;
    for(int i=0;i<graphicsItems.count();i++)
    {
        QGraphicsItem *CurItem=graphicsItems.at(i);
        if(CurItem->isVisible())
        {
            enabled_elements++;
        }
    }
   if(enabled_elements==0) return true;

   return false;
}

void QGraphicsPainter::undo()
{
    if (graphicsItems.isEmpty())
        return;
    //if(undo_item_index!=-1)
    //{
    //    QGraphicsItem *removedItem=graphicsItems.at(undo_item_index);
    //    scene()->removeItem(removedItem);
    //    undo_item_index=-1;
    //}

    /*QGraphicsItem **/ removedItems.append(graphicsItems.takeLast());
    undo_item_pos.append(removedItems.last()->pos().toPoint());
    //undo_item_index=graphicsItems.count();

    //if(graphicsItems.count()==1)
    //{
    //    undo_item_index=0;
    //}
    //undo_item_index = graphicsItems.count() - 1;
    removedItems.last()->setX(QApplication::desktop()->width());
    removedItems.last()->setY(QApplication::desktop()->height());

    if (removedItems.last() == selectedItem->item())
    {
        selectedItem->unselectItem();
    }
    //scene()->removeItem(removedItem);

    //delete removedItem;
    redo_enabled=true;



}
bool QGraphicsPainter::IsInNormalRect(int x,int y)
{


    int center_x=(width()/2)-(gr_rect.width()/2);
    int center_y=(height()/2)-(gr_rect.height()/2);
    int glb_width=center_x+scene()->width();
    int glb_height=center_y+scene()->height();
    picture_rect=QRect(center_x,center_y,glb_width,glb_height);


    if(x>=picture_rect.x()&&y>=picture_rect.y()&&x<(picture_rect.width())&&y<(picture_rect.height()))
    {
        return true;
    }
    else
    {
        return false;
    }
}

void QGraphicsPainter::mousePressEvent(QMouseEvent *event)
{


    if(IsInNormalRect(event->pos().x(),event->pos().y())==false)
    {
        holdLeftButton=false;

        return;
    }


    if (event->button() == Qt::LeftButton) {
        holdLeftButton = true;

        QPointF pos = mapToScene(event->pos());

        switch (paintMode())
        {
        case PaintModes::Brush:
            addBrushItem(pos);
            break;
        case PaintModes::Line:
            addLineItem(pos);
            break;
        case PaintModes::Arrow:
            addArrowItem(pos);
            break;
        case PaintModes::Text:
            addTextItem(pos);
            break;
        case PaintModes::Normal:
            if (selectedItem->hasSelectedItemInPoint(pos))
            {
                selectedItem->startMoving(pos);
            } else
            {
                selectItemByPoint(pos);
            }
            break;

        case PaintModes::MyText:


            break;

        }
    }

}

void QGraphicsPainter::mouseMoveEvent(QMouseEvent *event)
{

    QMouseEvent my_event(event->type(),event->pos(),Qt::LeftButton,Qt::NoButton,Qt::KeypadModifier);
    if(IsInNormalRect(event->pos().x(),event->pos().y())==false)
    {
        {

            if(holdLeftButton==true)
            {
                is_need_draw=1;
                mouseReleaseEvent(&my_event);
            }
        }
            holdLeftButton=false;
            return;
    }
    else
    {
        if(is_need_draw==1)
        {
            mousePressEvent(&my_event);
            is_need_draw=0;
            return;

        }

    }

    if (holdLeftButton)
    {
        QPointF pos = mapToScene(event->pos());

        switch (paintMode()) {
        case PaintModes::Brush:
            pos = brushItem->mapFromScene(pos);
            brushItem->addItemByPointOnScene(pos);
            break;
        case PaintModes::Line:
            pos = lineItem->mapFromScene(pos);
            lineItem->setLine(QLineF(firstPoint, pos));
            break;
        case PaintModes::Arrow:
            pos = arrowItem->mapFromScene(pos);
            arrowItem->setLine(QLineF(firstPoint, pos));
            break;
        case PaintModes::Text:
            pos = textItem->mapFromScene(pos);
            textItem->setRect(firstPoint, pos);

            break;
        case PaintModes::Normal:
            if (selectedItem->hasSelectedItem()) {
                selectedItem->continueMoving(pos);
            }
            break;
         case PaintModes::MyText:

            break;
        }
    }
}

void QGraphicsPainter::mouseReleaseEvent(QMouseEvent *event)
{

    if(IsInNormalRect(event->pos().x(),event->pos().y())==false)
    {
        holdLeftButton=false;

        return;
    }


    QPointF point=mapToScene(event->pos());
    if (event->button() == Qt::LeftButton)
    {
        switch(paintMode())
        {
        case PaintModes::Normal:
                break;

        case PaintModes::Arrow:
                arrowItem=new QGraphicsArrowItem();

                break;
        case PaintModes::Brush:
                brushItem=new QGraphicsBrushItem();
                break;
        case PaintModes::Line:
                lineItem=new QGraphicsLineItem();
                break;
        case PaintModes::Text:
                textItem=new QGraphicsTextRectItem();
                break;
        case PaintModes::MyText:
                item=new QGraphicsTextItem(textForPaint);
                QFont font=paintproperties.getTextFont();
                item->setDefaultTextColor(paintproperties.getBrushPen().color());
                item->setFont(font);
                if((point.x()+item->textWidth())>scene()->width())
                {
                    QString text_buffer;
                    for(int i=0;i<textForPaint.length();i++)
                    {
                        text_buffer=text_buffer.append(textForPaint.mid(i,1));

                        QGraphicsTextItem *tmp=new QGraphicsTextItem(text_buffer);
                        if(tmp->textWidth()>(point.x()+scene()->width()))
                        {
                            QString c;
                            c=text_buffer.mid(i,1);
                            text_buffer=text_buffer.mid(0,i-1);
                            text_buffer=text_buffer.append("\n");
                            item=new QGraphicsTextItem(text_buffer);

                            break;
                        }

                    }
                }
                item->setX(point.x());
                item->setY(point.y());
                addItem(item);

                break;


        }
    }
        holdLeftButton = false;
}

void QGraphicsPainter::mouseDoubleClickEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        selectedItem->unselectItem();
}

void QGraphicsPainter::clearAll()
{
    while (!graphicsItems.isEmpty())
        undo();
}

void QGraphicsPainter::showPaintProperties()
{
    paintproperties.show();
}

void QGraphicsPainter::addItem(QGraphicsItem *newItem)
{
    newItem->setBoundingRegionGranularity(0.25);
    graphicsItems.push_back(newItem);
    scene()->addItem(newItem);
    emit undoEnabled(true);
}

void QGraphicsPainter::addArrowItem(const QPointF &pos)
{
    arrowItem = new QGraphicsArrowItem;
    QGraphicsArrowItem *arrow_item=new QGraphicsArrowItem();
    arrow_item->setPen(paintproperties.getBrushPen());
    arrow_item->setPos(pos.x(),pos.y()+10);
    firstPoint=arrow_item->mapFromScene(pos);


    arrowItem->setPen(paintproperties.getBrushPen());
    arrowItem->setPos(pos);
    firstPoint = arrowItem->mapFromScene(pos);


    addItem(arrowItem);
}

void QGraphicsPainter::addLineItem(const QPointF &pos)
{
    lineItem = new QGraphicsLineItem;
    QPen pen;
    pen=paintproperties.getBrushPen();
    pen.setCapStyle(Qt::RoundCap);
    lineItem->setPen(pen);

    lineItem->setPos(pos);
    firstPoint = lineItem->mapFromScene(pos);
    addItem(lineItem);
}

void QGraphicsPainter::addBrushItem(const QPointF &pos)
{
    brushItem = new QGraphicsBrushItem;
    brushItem->setPen(paintproperties.getBrushPen());
    brushItem->addItemByPointOnScene(brushItem->mapFromScene(pos));
    addItem(brushItem);
}
void QGraphicsPainter::AddRectangle(const QPointF &pos)
{
    textItem = new QGraphicsTextRectItem;


    textItem->setPos(pos);
    firstPoint = textItem->mapFromScene(pos);
    addItem(textItem);
}

void QGraphicsPainter::addTextItem(const QPointF &pos)
{
    textItem = new QGraphicsTextRectItem;

    QColor color=paintproperties.getBrushPen().color();
    color.setAlpha(255);

    textItem->SetPen(QPen(color),paintproperties.getBrushPen().width());

    textItem->setDefaultTextColor(paintproperties.getBrushPen().color());
    textItem->setFont(paintproperties.getTextFont());
    textItem->setPos(pos);
    firstPoint = textItem->mapFromScene(pos);
    addItem(textItem);
}

void QGraphicsPainter::selectItemByPoint(const QPointF &pos, bool next)
{
    QGraphicsItem * item = NULL;
    QListIterator<QGraphicsItem *> iterator(graphicsItems);



    iterator.toBack();

    if (next && selectedItem->item() != NULL) {
        while (iterator.hasPrevious() && selectedItem->item() != iterator.previous()) {}
    }

    while (iterator.hasPrevious()) {
        item = iterator.previous();
    /*    QRectF boundingRect(item->boundingRect());
        boundingRect.moveTo(item->mapToScene(item->boundingRect().topLeft()));
        if (boundingRect.contains(pos))
        {
            selectedItem->SetMoveMaxRect(picture_rect);
            selectedItem->selectItem(item);
            selectedItem->startMoving(pos);
            return;
        }*/


        QRegion boundingRegion(item->boundingRegion(item->sceneTransform()));
        if(boundingRegion.contains(pos.toPoint()))
        {
            selectedItem->SetMoveMaxRect(picture_rect);
            selectedItem->selectItem(item);
            selectedItem->startMoving(pos);
            return;
        }



    }

    selectedItem->unselectItem();
}


